#ifndef BLOB_NET_H
#define BLOB_NET_H

/* Ethernet */
#define ETH_ALEN    6
#define ETHPROTO_IP    0x0800
#define ETHPROTO_ARP    0x0806
#define ETHPROTO_RARP    0x8035

/* IP */
#define IPPROTO_ICMP    1
#define IPPROTO_UDP    17

#define IP_DF        0x4000
#define IP_MF        0x2000
#define IP_OFFMASK    0x1fff

#define IPVERSION     4
#define MAXTTL        8

/* ARP */
#define ARPHDR_ETHER    1

#define ARP_REQUEST    1
#define ARP_REPLY    2
#define ARP_REVREQUEST    3
#define ARP_REVREPLY    4

/* ICMP */
#define ICMP_MINLEN    8

#define ICMP_ECHOREPLY    0
#define ICMP_UNREACH    3
#define ICMP_ECHO    8

struct etherhdr 
{
    unsigned char     eh_dhost[ETH_ALEN];
    unsigned char     eh_shost[ETH_ALEN];
    unsigned short     eh_proto;
}__attribute__ ((__packed__));

struct in_addr
{
    unsigned char addr[4];
}__attribute__ ((__packed__));

struct iphdr
{
    unsigned char     ip_hl : 4,
                  ip_v  : 4;
    unsigned char     ip_tos;
    short         ip_len;
    unsigned short    ip_id;
    short        ip_off;
    unsigned char    ip_ttl;
    unsigned char     ip_p;
    unsigned short    ip_sum;
    struct in_addr    ip_src, ip_dst;
}__attribute__ ((__packed__));

struct udphdr
{
    unsigned short     uh_sport;
    unsigned short     uh_dport;
    short        uh_len;
    unsigned short    uh_sum;
}__attribute__ ((__packed__));

struct udp_port {
    unsigned short port;
    int (*handler)();
};

struct icmphdr
{
    unsigned char    type; 
    unsigned char    code;
    unsigned short    cksum;
    union {
        struct in_addr    gwaddr;
        struct {
            unsigned short    id;
            unsigned short    seq;
        }idseq;
        struct {
            unsigned short     __unused;
            unsigned short    mtu;
        }mtu;
    } body;
}__attribute__ ((__packed__));

struct arphdr
{
    unsigned short    ar_hrd;
    unsigned short     ar_pro;
    unsigned char    ar_hln;
    unsigned char    ar_pln;
    unsigned short    ar_op;    
}__attribute__ ((__packed__));

struct ether_arp 
{
    struct    arphdr    ea_hdr;
    unsigned char    arp_sha[6];
    unsigned char    arp_spa[4];
    unsigned char    arp_tha[6];
    unsigned char     arp_tpa[4];
}__attribute__ ((__packed__));

#define BUFSZ    2048

struct mybuf{
    int len;
    unsigned char buf[BUFSZ];

    struct iphdr *ip;
    struct arphdr *arp;
    struct udphdr *udp;
    struct etherhdr *ether;
    struct ether_arp *etharp;
};

#define ntohs(x) ( ( ( (x) & 0xff ) << 8 ) |  ( ((x)>> 8) & 0xff) )
#define htons(x) ( ( ( (x) & 0xff ) << 8 ) |  ( ((x)>> 8) & 0xff) )


struct mybuf *bget(int io);
void net_rx();
void net_reset();

void net_init(void);
void net_test(void);
int cmd_tftp(u8* filename, u8* dest_address);
int cmd_ifconfig(u8* conf, u8* address);

#endif
